﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Domain.Dto;
using Domain.Dto.User;
using Domain.Interface;
using Domain.Model;
using Gmmy.DomainExtension;
using Gmmy.Utility;
using Gmmy.Utility.Extensions;
using Infrastructure.Common.Enums;
using Microsoft.VisualBasic.CompilerServices;
using Surging.Core.CPlatform.Ioc;
using Surging.Core.ProxyGenerator;

namespace Domain.Services
{

    [ModuleName(nameof(UserDomainService))]
    public class UserDomainService : ServiceBase, IUserDomainService
    {
        private readonly IUserRepoistory _repoistory;
        private readonly IUserRoleRepository _userRoleRepository;

        public UserDomainService(IUserRepoistory repoistory, IUserRoleRepository userRoleRepository)
        {
            _repoistory = repoistory;
            _userRoleRepository = userRoleRepository;
        }

        public async Task<LoginInfoDto> LoginAccount(string loginName, string password, string randomKey, RequestInfo loginInfo)
        {
            if (string.IsNullOrWhiteSpace(loginName) || string.IsNullOrWhiteSpace(password))
            {
                throw new CustomException("请输入用户名密码!");
            }
            var result = new LoginInfoDto();
            var user = (await _repoistory.GetByConditionAsync(new DirectSpecification<User>(x =>
                !x.IsDeleted && x.LoginName == loginName)));
            if (user != null)
            {
                if (user.PassWord ==
                    EncryptHelper.GetHMACSHA256(password + user.ID.ToString(), user.ID.ToString()))
                {
                    if (user.State == EnumUserState.Normal)
                    {
                        result = user.MapTo<LoginInfoDto,User>();
                        result.CustomerKey = randomKey;
                        user.UpdateLoginInfo(loginInfo);
                        _repoistory.Update(user, x => x.LastLoginIp, x => x.LastLoginTime);
                    }
                    else
                    {
                        throw new CustomException("当前账号已被冻结,无法登录!");
                    }
                }
                else
                {
                    throw new CustomException("用户名或密码错误!");
                }
            }
            else
            {
                throw new CustomException("用户名或密码错误!");
            }
            return result;
        }

        public async Task<LoginInfoDto> ChangeUserInfo(UpdateUserInput input)
        {
            var cacheUser = input.GetAuthInfo();
            var user = await _repoistory.GetByKeyAsync(input.ID ?? cacheUser.ID);
            if (user == null)
            {
                throw new CustomException("没有找到用户!");
            }
            user.ModifyAdditional(input);
            _repoistory.Update(user, x => x.NickName, x => x.PassWord);
            _userRoleRepository.LogicDelete(new DirectSpecification<UserRole>(x => x.UserId == user.ID));
            input.Roles.ForEach(x =>
            {
                _userRoleRepository.Add(new UserRole(user.ID, x));
            });
            return user.MapTo<LoginInfoDto, User>();
        }

        public async Task CreateUserInfo(UpdateUserInput input)
        {
            if (!await _repoistory.ExistsAsync(
                new DirectSpecification<User>(x => !x.IsDeleted && x.LoginName == input.LoginName)))
            {
                var user = new User(input);
                input.Roles.ForEach(x =>
                {
                    _userRoleRepository.Add(new UserRole(user.ID,x));
                });
                _repoistory.Add(user);
            }
            else
            {
                throw new CustomException("登录名重复了!");
            }
        }

        public async Task<EnumUserState> ChangeUserState(GetInput input)
        {
            var user = await _repoistory.GetByKeyAsync(input.ID);
            if (user == null)
            {
                throw new CustomException("没有找到用户!");
            }
            user.ChangeState(input);
            _repoistory.Update(user, x => x.State);
            return user.State;
        }
    }
}
